﻿/*
 * 作者: 谢中涞,博客园:http://www.cnblogs.com/xie-zhonglai
 * 欢迎转载,但请保留出处
 * */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using Xiezl.Common.LinqEx;

namespace Xiezl.Common.EFExpressions
{
    /// <summary>
    /// EFExpression 方法扩展
    /// </summary>
    public static class EFExpressionEx
    {
        #region SingleLogicEFExpression 扩展     
        /// <summary>
        /// 在当前条件基础上,添加构建一个like条件
        /// </summary>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static SingleLogicEFExpression<T> Like<T>(this SingleLogicEFExpression<T> old,
            Expression<Func<T, string>> property, string val) where T : class
        {
            if (old.Parameters == null || old.Parameters.Length == 0)
            {
                old.Parameters = property.Parameters.ToArray();
            }
            var tempExpression = new LikeEFExpression<T>(property, val);
            tempExpression.Parameters = old.Parameters;
            old.AddExpression(tempExpression.Expression);
            return old;
        }

        /// <summary>
        /// 在当前条件基础上,构建一个等于条件
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static SingleLogicEFExpression<T> Equal<T, TVal>(this SingleLogicEFExpression<T> old,
            Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            return createBinaryExpression(old, property, val, EBinaryType.Equal);
        }

        /// <summary>
        /// 在当前条件基础上,构建一个大于条件
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static SingleLogicEFExpression<T> GreaterThan<T, TVal>(this SingleLogicEFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            return createBinaryExpression(old, property, val, EBinaryType.GreaterThan);
        }

        /// <summary>
        /// 在当前条件基础上,构建一个大于或等于条件
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static SingleLogicEFExpression<T> GreaterThanOrEqual<T, TVal>(this SingleLogicEFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            return createBinaryExpression(old, property, val, EBinaryType.GreaterThanOrEqual);
        }

        /// <summary>
        /// 在当前条件基础上,构建一个小于条件
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static SingleLogicEFExpression<T> LessThan<T, TVal>(this SingleLogicEFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            return createBinaryExpression(old, property, val, EBinaryType.LessThan);
        }

        /// <summary>
        /// 在当前条件基础上,构建一个小于条件
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static SingleLogicEFExpression<T> LessThanOrEqual<T, TVal>(this SingleLogicEFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            return createBinaryExpression(old, property, val, EBinaryType.LessThanOrEqual);
        }

        /// <summary>
        /// 在当前条件基础上,构建一个小于条件,并且和当前条件产生And运算
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static SingleLogicEFExpression<T> NotEqual<T, TVal>(this SingleLogicEFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {           
            return createBinaryExpression(old, property, val, EBinaryType.NotEqual);
        }

        /// <summary>
        /// 建立 Between 查询条件
        /// </summary>
        /// <typeparam name="T">实体</typeparam>
        /// <param name="q">动态查询条件创建者</param>
        /// <param name="property">属性</param>
        /// <param name="from">开始值</param>
        /// <param name="to">结束值</param>
        /// <returns></returns>
        public static SingleLogicEFExpression<T> Between<T, P>(this SingleLogicEFExpression<T> old,
            Expression<Func<T, P>> property, P from, P to)
            where T : class
        {
            if (old.Parameters == null || old.Parameters.Length == 0)
            {
                old.Parameters = property.Parameters.ToArray();
            }
            var tempExpression = new BetweenEFExpression<T, P>(property, from, to);
            tempExpression.Parameters = old.Parameters;

            old.AddExpression(tempExpression.Expression);
            return old;
        }
        /// <summary>
        /// 构建in查询条件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="vals"></param>
        /// <returns></returns>
        public static SingleLogicEFExpression<T> In<T, TVal>(this SingleLogicEFExpression<T> old,
            Expression<Func<T, TVal>> property, params TVal[] vals)
            where T : class
        {
            if (old.Parameters == null || old.Parameters.Length == 0)
            {
                old.Parameters = property.Parameters.ToArray();
            }
            var tempExpression = new InEFExpression<T, TVal>(property, vals);
            tempExpression.Parameters = old.Parameters;

            old.AddExpression(tempExpression.Expression);
            return old;
        }

        /// <summary>
        /// 构建In查询条件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public static SingleLogicEFExpression<T> In<T, TVal>(this SingleLogicEFExpression<T> old,
            Expression<Func<T, TVal>> property, IEnumerable<TVal> values)
            where T : class
        {
            if (old.Parameters == null || old.Parameters.Length == 0)
            {
                old.Parameters = property.Parameters.ToArray();
            }
            var tempExpression = new InEFExpression<T, TVal>(property, values);
            tempExpression.Parameters = old.Parameters;

            old.AddExpression(tempExpression.Expression);
            return old;
        }

        /// <summary>
        /// 创建大于 小于 大于或等于 大于或小于条件 二元比较条件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="q"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private static SingleLogicEFExpression<T> createBinaryExpression<T, TVal>(SingleLogicEFExpression<T> old,
            Expression<Func<T, TVal>> property, TVal val, EBinaryType binaryType)
            where TVal : IComparable
            where T : class
        {
            if (old.Parameters == null || old.Parameters.Length == 0)
            {
                old.Parameters = property.Parameters.ToArray();
            }
            var binaryExp = new BinanryEfExpression<T, TVal>(property, binaryType, val);
            binaryExp.Parameters = old.Parameters;

            old.AddExpression(binaryExp.Expression);
            return old;
        }
        #endregion


        #region And运算扩展
        /// <summary>
        /// 在当前条件基础上,构建一个like条件,并且和当前条件产生And运算
        /// </summary>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static EFExpression<T> AndLike<T>(this EFExpression<T> old, Expression<Func<T, string>> property, string val) where T : class
        {
            var temp = new LikeEFExpression<T>(property, val);
            if (old == null)
                return temp;
            else
                return new LogicEFExpression<T>(old, ELogicType.And, temp);
        }

        /// <summary>
        /// 在当前条件基础上,构建一个等于条件,并且和当前条件产生And运算
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static EFExpression<T> AndEqual<T, TVal>(this EFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            var temp = new BinanryEfExpression<T, TVal>(property, EBinaryType.Equal, val);
            if (old == null)
                return temp;
            else
                return new LogicEFExpression<T>(old, ELogicType.And, temp);
        }

        /// <summary>
        /// 在当前条件基础上,构建一个大于条件,并且和当前条件产生And运算
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static EFExpression<T> AndGreaterThan<T, TVal>(this EFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            var temp = new BinanryEfExpression<T, TVal>(property, EBinaryType.GreaterThan, val);
            if (old == null)
                return temp;
            else
                return new LogicEFExpression<T>(old, ELogicType.And, temp);
        }
        /// <summary>
        /// 在当前条件基础上,构建一个大于或等于条件,并且和当前条件产生And运算
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static EFExpression<T> AndGreaterThanOrEqual<T, TVal>(this EFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            var temp = new BinanryEfExpression<T, TVal>(property, EBinaryType.GreaterThanOrEqual, val);
            if (old == null)
                return temp;
            else
                return new LogicEFExpression<T>(old, ELogicType.And, temp);
        }
        /// <summary>
        /// 在当前条件基础上,构建一个小于条件,并且和当前条件产生And运算
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static EFExpression<T> AndLessThan<T, TVal>(this EFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            var temp = new BinanryEfExpression<T, TVal>(property, EBinaryType.LessThan, val);
            if (old == null)
                return temp;
            else
                return new LogicEFExpression<T>(old, ELogicType.And, temp);
        }
        /// <summary>
        /// 在当前条件基础上,构建一个小于条件,并且和当前条件产生And运算
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static EFExpression<T> AndLessThanOrEqual<T, TVal>(this EFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            var temp = new BinanryEfExpression<T, TVal>(property, EBinaryType.LessThanOrEqual, val);
            if (old == null)
                return temp;
            else
                return new LogicEFExpression<T>(old, ELogicType.And, temp);
        }
        /// <summary>
        /// 在当前条件基础上,构建一个小于条件,并且和当前条件产生And运算
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static EFExpression<T> AndNotEqual<T, TVal>(this EFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            var temp = new BinanryEfExpression<T, TVal>(property, EBinaryType.NotEqual, val);
            if (old == null)
                return temp;
            else
                return new LogicEFExpression<T>(old, ELogicType.And, temp);
        }
        #endregion

        #region Or运算扩展
        /// <summary>
        /// 在当前条件基础上,构建一个like条件,并且和当前条件产生OR运算
        /// </summary>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static EFExpression<T> OrLike<T>(this EFExpression<T> old, Expression<Func<T, string>> property, string val) where T : class
        {
            var temp = new LikeEFExpression<T>(property, val);
            if (old == null)
                return temp;
            else
                return new LogicEFExpression<T>(old, ELogicType.Or, temp);
        }

        /// <summary>
        /// 在当前条件基础上,构建一个等于条件,并且和当前条件产生Or运算
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static EFExpression<T> OrEqual<T, TVal>(this EFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            var temp = new BinanryEfExpression<T, TVal>(property, EBinaryType.Equal, val);
            if (old == null)
                return temp;
            else
                return new LogicEFExpression<T>(old, ELogicType.Or, temp);
        }

        /// <summary>
        /// 在当前条件基础上,构建一个大于条件,并且和当前条件产生Or运算
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static EFExpression<T> OrGreaterThan<T, TVal>(this EFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            var temp = new BinanryEfExpression<T, TVal>(property, EBinaryType.GreaterThan, val);
            if (old == null)
                return temp;
            else
                return new LogicEFExpression<T>(old, ELogicType.Or, temp);
        }
        /// <summary>
        /// 在当前条件基础上,构建一个大于或等于条件,并且和当前条件产生Or运算
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static EFExpression<T> OrGreaterThanOrEqual<T, TVal>(this EFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            var temp = new BinanryEfExpression<T, TVal>(property, EBinaryType.GreaterThanOrEqual, val);
            if (old == null)
                return temp;
            else
                return new LogicEFExpression<T>(old, ELogicType.Or, temp);
        }
        /// <summary>
        /// 在当前条件基础上,构建一个小于条件,并且和当前条件产生Or运算
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static EFExpression<T> OrLessThan<T, TVal>(this EFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            var temp = new BinanryEfExpression<T, TVal>(property, EBinaryType.LessThan, val);
            if (old == null)
                return temp;
            else
                return new LogicEFExpression<T>(old, ELogicType.Or, temp);
        }
        /// <summary>
        /// 在当前条件基础上,构建一个小于条件,并且和当前条件产生Or运算
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static EFExpression<T> OrLessThanOrEqual<T, TVal>(this EFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            var temp = new BinanryEfExpression<T, TVal>(property, EBinaryType.LessThanOrEqual, val);
            if (old == null)
                return temp;
            else
                return new LogicEFExpression<T>(old, ELogicType.Or, temp);
        }
        /// <summary>
        /// 在当前条件基础上,构建一个小于条件,并且和当前条件产生Or运算
        /// </summary>
        /// <typeparam name="TVal"></typeparam>
        /// <param name="old"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static EFExpression<T> OrNotEqual<T, TVal>(this EFExpression<T> old, Expression<Func<T, TVal>> property, TVal val)
            where TVal : IComparable
            where T : class
        {
            var temp = new BinanryEfExpression<T, TVal>(property, EBinaryType.NotEqual, val);
            if (old == null)
                return temp;
            else
                return new LogicEFExpression<T>(old, ELogicType.Or, temp);
        }
        #endregion
    }
}
